home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mntlib43
/
mntlib
/
dirent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-11
|
4KB
|
219 lines
/* opendir/readdir/closedir routines */
/* under MiNT (v0.9 or better) these use the appropriate system calls.
* under TOS or older versions of MiNT, they use Fsfirst/Fsnext
*
* Written by Eric R. Smith and placed in the public domain
*/
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <limits.h>
#include <dirent.h>
#include <errno.h>
#include <osbind.h>
#include <mintbind.h>
#include "lib.h"
extern int __mint;
extern ino_t __inode; /* in stat.c */
DIR *
opendir(uname)
const char *uname;
{
DIR *d;
long r;
_DTA *olddta;
char name[PATH_MAX];
char dirpath[PATH_MAX];
char *p;
d = malloc(sizeof(DIR));
if (!d) {
errno = ENOMEM;
return d;
}
_unx2dos(uname, name);
if (__mint > 8) {
r = Dopendir(name, 0);
if ( (r & 0xff000000L) == 0xff000000L ) {
errno = (int) -r;
free(d);
return 0;
}
d->handle = r;
d->buf.d_off = 0;
return d;
}
/* TOS emulation routines */
p = name;
if (p) {
/* find the end of the string */
for (p = name; *p; p++) ;
/* make sure the string ends in '\' */
if (*(p-1) != '\\') {
*p++ = '\\';
}
}
strcpy(p, "*.*");
olddta = Fgetdta();
Fsetdta(&(d->dta));
r = Fsfirst(name, 0x17);
Fsetdta(olddta);
if (r == 0) {
d->status = _STARTSEARCH;
} else if (r == -ENOENT) {
d->status = _NMFILE;
} else {
free(d);
errno = (int) -r;
return 0;
}
d->buf.d_off = 0;
/* for rewinddir: if necessary, build a relative path */
if (name[1] == ':') { /* absolute path, no problem */
dirpath[0] = 0;
} else {
dirpath[0] = Dgetdrv() + 'A';
dirpath[1] = ':';
dirpath[2] = 0;
if (*name != '\\')
(void)Dgetpath(dirpath+2, 0);
}
d->dirname = malloc(strlen(dirpath)+strlen(name)+1);
if (d->dirname) {
strcpy(d->dirname, dirpath);
strcat(d->dirname, name);
}
return d;
}
struct dirent *
readdir(d)
DIR *d;
{
struct dbuf {
long ino;
char name[NAME_MAX + 1];
} dbuf;
long r;
_DTA *olddta;
struct dirent *dd = &d->buf;
if (__mint > 8) {
r = (int)Dreaddir((int)(NAME_MAX+1+sizeof(long)), d->handle, (char *) &dbuf);
if (r == -ENMFIL)
return 0;
else if (r) {
errno = (int) -r;
return 0;
}
dd->d_ino = dbuf.ino;
dd->d_off++;
dd->d_reclen = (short)strlen(dbuf.name);
strcpy(dd->d_name, dbuf.name);
return dd;
}
/* ordinary TOS search, using Fsnext. Note that the first time through,
* Fsfirst has already provided valid data for us; for subsequent
* searches, we need Fsnext.
*/
if (d->status == _NMFILE)
return 0;
if (d->status == _STARTSEARCH) {
d->status = _INSEARCH;
} else {
olddta = Fgetdta();
Fsetdta(&(d->dta));
r = Fsnext();
Fsetdta(olddta);
if (r == -ENMFIL) {
d->status = _NMFILE;
return 0;
} else if (r) {
errno = (int)-r;
return 0;
}
}
dd->d_ino = __inode++;
dd->d_off++;
_dos2unx(d->dta.dta_name, dd->d_name);
dd->d_reclen = (short)strlen(dd->d_name);
return dd;
}
void
rewinddir(dirp)
DIR *dirp;
{
long r;
_DTA *olddta;
if (__mint >= 9) {
(void)Drewinddir(dirp->handle);
dirp->buf.d_off = 0;
return;
}
/* I wish POSIX had allowed an error to occur here! */
if (!dirp->dirname) {
return;
}
olddta = Fgetdta();
Fsetdta(&(dirp->dta));
r = Fsfirst(dirp->dirname, 0x17);
Fsetdta(olddta);
if (r == 0) {
dirp->status = _STARTSEARCH;
} else {
dirp->status = _NMFILE;
}
dirp->buf.d_off = 0;
}
int
closedir(dirp)
DIR *dirp;
{
int r;
if (__mint > 8) {
r = (int)Dclosedir(dirp->handle);
} else {
r = 0;
}
free(dirp);
return r;
}
/* the next two aren't POSIX, but lots of people have them */
off_t
telldir(dirp)
DIR *dirp;
{
return dirp->buf.d_off;
}
void
seekdir(dirp, loc)
DIR *dirp;
off_t loc;
{
rewinddir(dirp);
while (dirp->buf.d_off != loc) {
if (!readdir(dirp))
break;
}
}